﻿using Magicodes.ExporterAndImporter.Core;
using Microsoft.AspNetCore.Http;
namespace Admin.NET.Application;

/// <summary>
/// 客户档案表服务
/// </summary>
[ApiDescriptionSettings(ApplicationConst.GroupName, Order = 100)]
public class CustomerService : IDynamicApiController, ITransient
{
    private readonly SqlSugarRepository<Customer> _customerRep;
    private readonly SqlSugarRepository<CustomerChannel> _customerChannelRep;
    private readonly UserManager _userManager;
    private readonly IImporter _importer;

    public CustomerService(SqlSugarRepository<Customer> customerRep,
        UserManager userManager,
        SqlSugarRepository<CustomerChannel> customerChannelRep,
        IImporter importer)
    {
        _customerRep = customerRep;
        _userManager = userManager;
        _customerChannelRep = customerChannelRep;
        _importer = importer;
    }


    public class PagedDataWithSums
    {
        public SqlSugarPagedList<CustomerOutput> PageData { get; set; }
        public double TotalMoney { get; set; }
        public int TotalQuantity { get; set; }
    }


    /// <summary>
    /// 分页查询客户档案表
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    [ApiDescriptionSettings(Name = "Page")]
    [DisplayName("分页查询客户档案表")]
    public async Task<PagedDataWithSums> Page(PageCustomerInput input)
    {
        input.SearchKey = input.SearchKey?.Trim();
        var query = _customerRep.AsQueryable()
            .LeftJoin<SysUser>((u, b) => u.CreateUserId == b.Id)
            .LeftJoin<SysOrg>((u, b, c) => b.OrgId == c.Id)
            .WhereIF(!string.IsNullOrEmpty(input.SearchKey), (u, b, c) =>
                u.CusName.Contains(input.SearchKey)
                || u.Remark.Contains(input.SearchKey)
                || u.VoucherRemark.Contains(input.SearchKey)
                || u.SourceChanneName.Contains(input.SearchKey)
                || u.CreateUserName.Contains(input.SearchKey)
                || c.Name.Contains(input.SearchKey)
            )
            .WhereIF(!string.IsNullOrWhiteSpace(input.CusName), u => u.CusName.Contains(input.CusName.Trim()))
            .WhereIF(input.CreateUserId > 0, u => u.CreateUserId == input.CreateUserId)
            .WhereIF(input.OrgId > 0, (u, b, c) => c.Id == input.OrgId)
            .WhereIF(input.Type > 0, u => u.Type.ToString() == input.Type.ToString())
            .WhereIF(input.SourceChanne > 0, u => u.SourceChanne.ToString() == input.SourceChanne.ToString())
            .WhereIF(input.IsCollected > -1, u => u.IsCollected == (input.IsCollected == 1 ? true : false))
            .WhereIF(input.IsReport > -1, u => u.IsReport == (input.IsReport == 1 ? true : false))

            .WhereIF(input.CollectedTimeRange != null && input.CollectedTimeRange.Length == 2, u => u.CollectedTime >= input.CollectedTimeRange[0] && u.CollectedTime <= input.CollectedTimeRange[1])
            .WhereIF(input.ReportTimeRange != null && input.ReportTimeRange.Length == 2, u => u.ReportTime >= input.ReportTimeRange[0] && u.ReportTime <= input.ReportTimeRange[1])
            .WhereIF(!string.IsNullOrWhiteSpace(input.Remark), u => u.Remark.Contains(input.Remark.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(input.SourceChanneName), u => u.SourceChanneName.Contains(input.SourceChanneName.Trim()))
            .WhereIF(!(_userManager.SuperAdmin || _userManager.SysAdmin), u => u.CreateUserId == _userManager.UserId)
            .WhereIF(true, u => u.IsDelete == false)
            .Select((u, b, c) => new CustomerOutput
            {
                Id = u.Id,
                OrgName = c.Name,
                CusName = u.CusName,
                Type = (int)u.Type,
                Quantity = u.Quantity,
                Money = u.Money,
                PropertyMoney = u.PropertyMoney,
                IsCollected = u.IsCollected,
                IsReport = u.IsReport,
                CollectedTime = u.CollectedTime,
                ReportTime = u.ReportTime,
                Remark = u.Remark,
                SourceChanne = (int)u.SourceChanne,
                SourceChanneName = u.SourceChanneName,
                VoucherImg = u.VoucherImg,
                CreateTime = u.CreateTime,
                UpdateTime = u.UpdateTime,
                CreateUserId = u.CreateUserId,
                CreateUserName = u.CreateUserName,
                UpdateUserId = u.UpdateUserId,
                UpdateUserName = u.UpdateUserName,
                IsDelete = u.IsDelete,
                VoucherRemark = u.VoucherRemark
            })
            .MergeTable();

        // 获取当前查询条件下所有数据的 Sum(Money) 值
        double totalMoney = await query.SumAsync(u => u.Money);
        int quantity = await query.SumAsync(u => u.Quantity);

        //.Select<CustomerOutput>();
        //return await query.OrderBuilder(input).ToPagedListAsync(input.Page, input.PageSize);

        // 合并查询总和
        //var totalSums = await query.Select(x => new xxx
        //{
        //    TotalMoney = SqlFunc.AggregateSum(x.Money),
        //    TotalPropertyMoney = SqlFunc.AggregateSum(x.PropertyMoney.Value),
        //    TotalQuantity = SqlFunc.AggregateSum(x.Quantity)
        //}).FirstAsync();

        //var totalSums = query.Select(x => new
        //{
        //    TotalMoney = SqlFunc.AggregateSum(x.Money),
        //    TotalPropertyMoney = SqlFunc.AggregateSum(x.PropertyMoney.Value),
        //    TotalQuantity = SqlFunc.AggregateSum(x.Quantity)
        //}).FirstAsync();

        var pageData = await query.OrderBuilder(input).ToPagedListAsync(input.Page, input.PageSize);

        return new PagedDataWithSums
        {
            PageData = pageData,
            TotalMoney = totalMoney,
            TotalQuantity = quantity
        };
    }

    /// <summary>
    /// 增加客户档案表
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    [ApiDescriptionSettings(Name = "Add")]
    [DisplayName("增加客户档案表")]
    public async Task<long> Add(AddCustomerInput input)
    {
        var entity = input.Adapt<Customer>();
        await _customerRep.InsertAsync(entity);
        return entity.Id;
    }

    /// <summary>
    /// 删除客户档案表
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    [ApiDescriptionSettings(Name = "Delete")]
    [DisplayName("删除客户档案表")]
    public async Task Delete(DeleteCustomerInput input)
    {
        var entity = await _customerRep.GetFirstAsync(u => u.Id == input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D1002);
        await _customerRep.FakeDeleteAsync(entity);   //假删除
        //await _customerRep.DeleteAsync(entity);   //真删除
    }

    /// <summary>
    /// 更新客户档案表
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    [ApiDescriptionSettings(Name = "Update")]
    [DisplayName("更新客户档案表")]
    public async Task Update(UpdateCustomerInput input)
    {
        var entity = input.Adapt<Customer>();
        await _customerRep.AsUpdateable(entity).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync();
    }

    /// <summary>
    /// 获取客户档案表
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpGet]
    [ApiDescriptionSettings(Name = "Detail")]
    [DisplayName("获取客户档案表")]
    public async Task<Customer> Detail([FromQuery] QueryByIdCustomerInput input)
    {
        return await _customerRep.GetFirstAsync(u => u.Id == input.Id);
    }

    /// <summary>
    /// 获取客户档案表列表
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpGet]
    [ApiDescriptionSettings(Name = "List")]
    [DisplayName("获取客户档案表列表")]
    public async Task<List<CustomerOutput>> List([FromQuery] PageCustomerInput input)
    {
        return await _customerRep.AsQueryable().Select<CustomerOutput>().ToListAsync();
    }


    /// <summary>
    /// 导出客户模板
    /// </summary>
    /// 
    [HttpGet]
    [DisplayName("导出客户档案模板")]
    [ApiDescriptionSettings(Name = "DownloadExcelTemplate")]
    public async Task<IActionResult> DownloadExcelTemplate()
    {
        var result = await this.ExportExcelTemplateV2<CustomerImportDto>("客户档案表");
        return result;
    }

    private async Task<IActionResult> ExportExcelTemplateV2<T>(string fileName = null) where T : class, new()
    {
        var res = await _importer.GenerateTemplateBytes<T>();
        return new FileContentResult(res, "application/octet-stream") { FileDownloadName = $"{(string.IsNullOrEmpty(fileName) ? typeof(T).Name : fileName)}.xlsx" };
    }



    [HttpPost]
    [DisplayName("导入客户档案")]
    [ApiDescriptionSettings(Name = "ImportDataCus")]
    public async Task ImportData([Required] IFormFile file)
    {
        List<Customer> list = new();
        try
        {
            var rows = await CommonUtil.ImportExcelData<CustomerImportDto>(file);
            foreach (var item in rows)
            {
                var entity = item.Adapt<Customer>();
                if (!string.IsNullOrWhiteSpace(item.SourceChanneStr))
                {
                    var tempChanne = _customerChannelRep.GetFirst(x => x.Name == item.SourceChanneStr);
                    if (tempChanne != null)
                        entity.SourceChanne = tempChanne.Id;
                }
                list.Add(entity);
            }
            var r = _customerRep.InsertOrUpdate(list);
        }
        catch (Exception ex)
        {
            throw Oops.Oh($"导入失败：{ex.Message}");
        }
    }


    /// <summary>
    /// 批量删除
    /// </summary>
    /// <param name="ids"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "BatchDelete"), HttpPost]
    [DisplayName("批量删除客户")]
    public async Task BatchDeleteCustomer(List<long> ids)
    {
        await _customerRep.DeleteAsync(x => ids.Contains(x.Id));
    }



    /// <summary>
    /// 批量收款
    /// </summary>
    /// <param name="ids"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "BatchCollectMoney"), HttpPost]
    [DisplayName("批量收款")]
    public async Task BatchCollectMoney(List<long> ids)
    {
        foreach (var id in ids)
        {
            var cust = await _customerRep.GetFirstAsync(u => u.Id == id);
            if (cust == null)
                continue;

            cust.IsCollected = true;
            cust.CollectedTime = DateTime.Now;

            await _customerRep.UpdateAsync(cust);
        }
    }


}
